/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 4; tab-width: 4 -*- */
/*
 * StructureNetwork
 * Copyright (C) Michele Vidotto 2008 <vid1998@email.it>
 * 
 * StructureNetwork is free software: you can redistribute it and/or modify it
 * under the terms of the GNU General Public License as published by the
 * Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 * 
 * StructureNetwork is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 * See the GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License along
 * with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

#include "StructureNetwork.h"
#include <string>
#include <GetArg.h> // Classe dentro a tool
#include <PdbLoader.h>
#include <AminoAcidCode.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <cassert>
#include <math.h>
#include <vector3.h>
#include <IntCoordConverter.h>
#include <stdio.h>
#include <time.h>


#define PI 3.14159265


using namespace Biopool;
using namespace std;

//Inizializzazione dei parametri di default di HBonds
StructureNetwork::HBonds::HBonds()
:don_num(0), acc_num(0), h_bond_length(0), h_bond_angle(0), 
don_code(' '), acc_code(' '), is_main(false)
{
}

//Inizializzazione dei parametri di default di SaltBridge
StructureNetwork::SaltBridge::SaltBridge()
:positive_num(0), negative_num(0), bridge_length(0), bridge_angle(0), 
positive_code(' '), negative_code(' ')
{
}

StructureNetwork::DisulfideBond::DisulfideBond()
:bond_length(0), xss_angle(0)
{
}


//Inizializzazione dei parametri di default di TypeOfConnection
StructureNetwork::TypeOfConnection::TypeOfConnection()
:aa_i_code(' '), aa_j_code(' '), distance(0), is_h_bond(false), is_salt_bridge(false), is_disulfide_bond(false)
{
}

/* 
 UTILE PER MODIFICARE I DATI MEMBRO DELLA CLASSE ANNIDATA TYPEOFCONNECTION
 
 void StructureNetwork::TypeOfConnection::set( int x )
{
	cout <<"ciao" <<endl;
} */


/*
	Costruttore
 	Setto i dati membro con i valori di default
*/
StructureNetwork::StructureNetwork(string input_file)
{
	SetAlpha(false);
	SetClosatom(false);
	SetMaxDistanceOfAlpha(8.5);
	SetMaxDistanceOfClosest(5.0);
	SetInputFile(input_file);
	LoadSpacer();
	EraseMatrixOfDistance();
}

/*
	Carica il percorso del file pdb nel dato membro input_file_path.
 	Se il percorso è corretto restituisce true. Se è vuoto restituisce false
*/
bool StructureNetwork::SetInputFile(string input_file_pass)
{
	if (input_file_pass == "")
	{
		cout << "Invalid path file." << endl;
		return false;
		
	}
	
	input_file_path = input_file_pass;
	return true;
}

/*
	Modifica il limite superiore di vicinanza tra carboni alfa
*/
void StructureNetwork::SetMaxDistanceOfAlpha(double max_distance_of_alpha_pass)
{
	if (max_distance_of_alpha_pass > 0)
	{
		max_distance_of_alpha = max_distance_of_alpha_pass;
	}
}

/*
	Restituisce il limite superiore di vicinanza tra carboni alfa
*/
double StructureNetwork::GetMaxDistanceOfAlpha() const
{
	return max_distance_of_alpha;  
}

/*
	Modifica il limite superiore di vicinanza tra atomi di aminoacidi in contatto
*/
void StructureNetwork::SetMaxDistanceOfClosest(double max_distance_of_closest_pass)
{
	max_distance_of_closest = max_distance_of_closest_pass; 
}

/*
	Restituisce il limite superiore di vicinanza tra atomi di aminoacidi in contatto
*/
double StructureNetwork::GetMaxDistanceOfClosest() const
{
	return max_distance_of_closest;  
}

/*
	Carica il Pdb in uno spacer
 	Se il file è vuoto lancia un'eccezione
*/
void StructureNetwork::LoadSpacer()
{	
	cout << "Processing " << input_file_path <<"..." << endl;
	
	ifstream inFile(input_file_path.c_str());

	if (!inFile) // if ( !inFile.good() )
	ERROR("file not found.", exception);

	PdbLoader pl(inFile);
	pl.setNoHAtoms(); //non carica gli atomi di idrogeno
	pl.setNoVerbose();
	
	sp.load(pl);
}

/*
 	Prepara la matrice di distanza definendo i parametri di TypeOfConnection di default
 	Si tratta di una matrice quadrata con le dimensioni dello spacer
*/
void StructureNetwork::EraseMatrixOfDistance()
{
	distance_matrix.erase(distance_matrix.begin(), distance_matrix.end());
	
	for (int i=0; i < sp.sizeAmino(); i++)
	{
		vector <TypeOfConnection> colonna;
		 
		for (int j=0; j < sp.sizeAmino(); j++)
		{
			TypeOfConnection tmp; 
			colonna.push_back(tmp); 
		}
		
		distance_matrix.push_back(colonna);					 
	}
}

/*
 	Restituisce l'elemento della matrice corrispondente alla i-esima riga e j-esima colonna
*/
StructureNetwork::TypeOfConnection StructureNetwork::GetDistanceMatrix(int i, int j) const
{
	assert((i>=0) && (i< distance_matrix.size()));
	assert((j>=0) && (j< distance_matrix.size()));
	
	return distance_matrix[i][j];
}


/*
 	Calcola la distanza tra i carboni alfa di un aminoacido con quello nella 
 	posizione i+3 e i-3
 	L'applicazione di questo metodo su un oggetto escluda l'applicazione del
 	metodo CalculateClosestAtomDistance()
*/
void StructureNetwork::CalculateCAlphaDistance()
{
	if ((alpha==false)&&(closatom==false))
	{
		double distance;
		
		//Confronto di distanze secondo matrice diagonale
		for(int i=0; i < sp.sizeAmino()-3; i++)
		{   
		
		
			for (int j=i+3; j < sp.sizeAmino(); j++)
			{	
				distance_matrix[i][j].aa_i_code = sp.getAmino(i).getType1L();
				distance_matrix[i][j].atom_i_code = "CA";
				distance_matrix[i][j].aa_j_code = sp.getAmino(j).getType1L();
				distance_matrix[i][j].atom_j_code = "CA";
			
				distance = sp.getAmino(i)[CA].distance(sp.getAmino(j)[CA]);
				if (distance <= max_distance_of_alpha) //Distanza massima per contatto
				{
					distance_matrix[i][j].distance = MyRound(distance,2);	
				}
			}
		}
		
		alpha=true;
	}
	else
	{
		cout << "A different method of calculation has already been applied on this object. Run the method on a new object!" << endl;
	}
}


/*
 	Calcolo della distanza considerando l'atomo più vicino di un aminoacido con 
 	quello nella posizione i+2 e i-2
 	L'applicazione di questo metodo su un oggetto escluda l'applicazione del
 	metodo CalculateCAlphaDistance()
*/
void StructureNetwork::CalculateClosestAtomDistance()
{
	if ((alpha==false)&&(closatom==false))
	{
		double distance;

		for (int i=0; i < sp.sizeAmino()-2; i++)
		
		for (int j=i+2; j < sp.sizeAmino(); j++)
		{
			
			double min = max_distance_of_closest;
			
			distance_matrix[i][j].aa_i_code = sp.getAmino(i).getType1L();
			distance_matrix[i][j].aa_j_code = sp.getAmino(j).getType1L();
			
			for (int k = 0; k < sp.getAmino(i).size(); k++)			
			{
				for(int s = 0; s < sp.getAmino(j).size(); s++)
				{
						
           			distance = sp.getAmino(i)[k].distance(sp.getAmino(j)[s]);
/*if ((sp->getAmino(i).getType1L() == 'G') || (sp->getAmino(j).getType1L() == 'G')) //controllo glicine
//cout << distance << " glicina" << endl;*/
					if ( distance <= min )	//Condizione per contatto
					{
							min = distance;
							distance_matrix[i][j].distance = MyRound(distance,2);
							distance_matrix[i][j].atom_i_code = sp.getAmino(i)[k].getType();
							distance_matrix[i][j].atom_j_code = sp.getAmino(j)[s].getType();
					}
				}
           
			}

		}
		alpha=false;
		closatom=true;
	}
	else
	{
		cout << "A different method of calculation has already been applied on this object. Run the method on a new object!" << endl;
	}
}

/*
	Modifica il booleano alpha che controlla se è già stato applicato il 
 	metodo CalculateCAlphaDistance()
*/
void StructureNetwork::SetAlpha(bool alpha_pass)
{
	alpha = alpha_pass;
}

/*
	Modifica il booleano closatom che controlla se è già stato applicato il 
 	metodo CalculateClosestAtomDistance()
*/
void StructureNetwork::SetClosatom(bool closatom_pass)
{
	closatom = closatom_pass;
}

/*
	Stampa gli elementi di una cella della matrice di distanze in 3 file acquisibili
 	da Cytoscape:
 
 	-sif_name: file .sif che definisce i contatti fra i nodi
 
 	-edge_atrib_name: file di attributo .EA che definisce come attributo di ciascun contatto
 	 quali sono gli atomi che determinano tale contatto
 	
 	-edge_distance: file di attributo .EA che definisce come attributo di ciascun contatto
 	 la distanza di tale contatto
 
 	La prima riga di ogni file di attributo deve contenere una intestazione che determina
 	il tipo di dato che definisce l'attributo:
 	-es: Edge_Atrib_Atom_Alpha (class=java.lang.XXXX)
	 	 con XXXX = String	(stringa di caratteri)
		 			Double	(numero decimale)
		 			Integer	(numero intero)
*/
void  StructureNetwork::ClosestPrintFilesAllHbonds(string net_sif_file, 
								   string edge_atrib_atom_type, 
								   string edge_atrib_atom_type_header, 
								   string edge_atrib_distance, 
								   string edge_atrib_distance_header, 
								   string edge_atrib_hbond_DA, 
								   string edge_atrib_hbond_DA_header, 
								   string edge_atrib_hb_DA_distance, 
								   string edge_atrib_hb_DA_distance_header, 
								   string edge_atrib_hb_DHA_angle, 
								   string edge_atrib_hb_DHA_angle_header,
								   string edge_atrib_salt_P_N,
								   string edge_atrib_salt_P_N_header,
								   string edge_atrib_salt_distance,
								   string edge_atrib_salt_distance_header,
								   string edge_atrib_salt_angle,
								   string edge_atrib_salt_angle_header,
								   string edge_atrib_disulfide_distance,
								   string edge_atrib_disulfide_distance_header,
								   string edge_atrib_disulfide_angle,
								   string edge_atrib_disulfide_angle_header)
{
		string input_file_path_pass;
//------------------------------------------------------------------------------			
		input_file_path_pass = input_file_dir + net_sif_file;
	
		ofstream sifFile(input_file_path_pass.c_str()); 
//------------------------------------------------------------------------------
		input_file_path_pass = input_file_dir + edge_atrib_atom_type;

		ofstream edgeAtribAtom(input_file_path_pass.c_str());

		edgeAtribAtom << edge_atrib_atom_type_header << endl;
//------------------------------------------------------------------------------
		input_file_path_pass = input_file_dir + edge_atrib_distance;

		ofstream edgeAtribDist(input_file_path_pass.c_str());

		edgeAtribDist << edge_atrib_distance_header << endl;
//------------------------------------------------------------------------------
		input_file_path_pass = input_file_dir + edge_atrib_hbond_DA;
	
		ofstream edgeAtribHbondDA(input_file_path_pass.c_str());
	
		edgeAtribHbondDA << edge_atrib_hbond_DA_header << endl;
//------------------------------------------------------------------------------
		input_file_path_pass = input_file_dir + edge_atrib_hb_DA_distance;
		
		ofstream edgeAtribHbDAdistance(input_file_path_pass.c_str());
	
		edgeAtribHbDAdistance << edge_atrib_hb_DA_distance_header << endl;
//------------------------------------------------------------------------------
		input_file_path_pass = input_file_dir + edge_atrib_hb_DHA_angle;
	
	 	ofstream edgeAtribHbDHAangle(input_file_path_pass.c_str());
	
		edgeAtribHbDHAangle << edge_atrib_hb_DHA_angle_header << endl;
//------------------------------------------------------------------------------
		input_file_path_pass = input_file_dir + edge_atrib_salt_P_N;
	
		ofstream edgeAtribSaltPN(input_file_path_pass.c_str());
	
		edgeAtribSaltPN << edge_atrib_salt_P_N_header << endl;
//------------------------------------------------------------------------------
		input_file_path_pass = input_file_dir + edge_atrib_salt_distance;
		
		ofstream edgeAtribSaltDistance(input_file_path_pass.c_str());
	
		edgeAtribSaltDistance << edge_atrib_salt_distance_header << endl;
//------------------------------------------------------------------------------
		input_file_path_pass = input_file_dir + edge_atrib_salt_angle;
	
		ofstream edgeAtribSaltAngle(input_file_path_pass.c_str());
	
		edgeAtribSaltAngle << edge_atrib_salt_angle_header << endl;
//------------------------------------------------------------------------------
		input_file_path_pass = input_file_dir + edge_atrib_disulfide_distance;
	
		ofstream edgeAtribDisulfideDistance(input_file_path_pass.c_str());
	
		edgeAtribDisulfideDistance << edge_atrib_disulfide_distance_header << endl;
//------------------------------------------------------------------------------
		input_file_path_pass = input_file_dir + edge_atrib_disulfide_angle;
	
		ofstream edgeAtribDisulfideAngle(input_file_path_pass.c_str());
	
		edgeAtribDisulfideAngle << edge_atrib_disulfide_angle_header << endl;
//------------------------------------------------------------------------------
		
		for (int i = 0; i< distance_matrix.size(); i++)
			
			for (int j = 0; j < distance_matrix[i].size(); j++)
			{
	  			if (distance_matrix[i][j].distance != 0.0)
				{	
//------------------------------------------------------------------------------
					if (distance_matrix[i][j].is_salt_bridge==true)
					{
						
						for (int x=0; x < distance_matrix[i][j].salt_bridge.size(); x++)
						{	
							sifFile << distance_matrix[i][j].salt_bridge[x].positive_code
									<< "_" 
									<< distance_matrix[i][j].salt_bridge[x].positive_num
									<< "\trr\t"
									<< distance_matrix[i][j].salt_bridge[x].negative_code
									<< "_"
									<< distance_matrix[i][j].salt_bridge[x].negative_num
									<< endl;
							
					edgeAtribAtom << distance_matrix[i][j].salt_bridge[x].positive_code
								  << "_"
								  << distance_matrix[i][j].salt_bridge[x].positive_num
								  << " (rr) " 
								  << distance_matrix[i][j].salt_bridge[x].negative_code
								  << "_" 
								  << distance_matrix[i][j].salt_bridge[x].negative_num
								  << "\t=\t" 
								  << distance_matrix[i][j].salt_bridge[x].atom_positive_code 
								  << "_" 
								  << distance_matrix[i][j].salt_bridge[x].atom_negative_code
								  << endl;
							
					edgeAtribDist << distance_matrix[i][j].salt_bridge[x].positive_code
								  << "_" 
								  << distance_matrix[i][j].salt_bridge[x].positive_num
								  << " (rr) " 
								  << distance_matrix[i][j].salt_bridge[x].negative_code
								  << "_" 
								  << distance_matrix[i][j].salt_bridge[x].negative_num
								  << "\t=\t" 
								  << distance_matrix[i][j].distance
								  << endl;
							
				 edgeAtribSaltPN << distance_matrix[i][j].salt_bridge[x].positive_code
								 << "_" 
								 << distance_matrix[i][j].salt_bridge[x].positive_num
								 << " (rr) "
								 << distance_matrix[i][j].salt_bridge[x].negative_code
								 << "_"
								 << distance_matrix[i][j].salt_bridge[x].negative_num
								 << "\t=\t"
								 << distance_matrix[i][j].salt_bridge[x].positive_code
								 << "->"
								 << distance_matrix[i][j].salt_bridge[x].negative_code
								 << endl;
			
									
			edgeAtribSaltDistance << distance_matrix[i][j].salt_bridge[x].positive_code
								  << "_" 
								  << distance_matrix[i][j].salt_bridge[x].positive_num
								  << " (rr) "
								  << distance_matrix[i][j].salt_bridge[x].negative_code
								  << "_"
								  << distance_matrix[i][j].salt_bridge[x].negative_num
								  << "\t=\t"
								  << distance_matrix[i][j].salt_bridge[x].bridge_length
								  << endl;
									
			   edgeAtribSaltAngle << distance_matrix[i][j].salt_bridge[x].positive_code
								  << "_" 
								  << distance_matrix[i][j].salt_bridge[x].positive_num
								  << " (rr) "
								  << distance_matrix[i][j].salt_bridge[x].negative_code
								  << "_"
								  << distance_matrix[i][j].salt_bridge[x].negative_num
								  << "\t=\t"
								  << distance_matrix[i][j].salt_bridge[x].bridge_angle 
								  << endl;
							
						}
					}	
					
					else
					{	
//------------------------------------------------------------------------------	
					if(distance_matrix[i][j].is_h_bond==true)
					{
						for (int x=0; x < distance_matrix[i][j].h_bonds.size(); x++)
							{
								if (distance_matrix[i][j].h_bonds[x].is_main==true)
								{
									sifFile << distance_matrix[i][j].h_bonds[x].don_code
											<< "_" 
											<< distance_matrix[i][j].h_bonds[x].don_num
											<< "\trr\t"
											<< distance_matrix[i][j].h_bonds[x].acc_code
											<< "_"
											<< distance_matrix[i][j].h_bonds[x].acc_num
											<< endl;
									
									edgeAtribAtom << distance_matrix[i][j].h_bonds[x].don_code 
								  				  << "_"
								  				  << distance_matrix[i][j].h_bonds[x].don_num 
								  				  << " (rr) " 
												  << distance_matrix[i][j].h_bonds[x].acc_code 
								  				  << "_" 
								  				  << distance_matrix[i][j].h_bonds[x].acc_num
								  				  << "\t=\t" 
												  << distance_matrix[i][j].h_bonds[x].atom_don_code
								  				  << "_" 
								  				  << distance_matrix[i][j].h_bonds[x].atom_acc_code
								  				  << endl;
									
									edgeAtribDist << distance_matrix[i][j].h_bonds[x].don_code
								  				  << "_" 
								  				  << distance_matrix[i][j].h_bonds[x].don_num
								                  << " (rr) " 
								 				  << distance_matrix[i][j].h_bonds[x].acc_code 
								  				  << "_" 
								  				  << distance_matrix[i][j].h_bonds[x].acc_num 
								 				  << "\t=\t" 
								  				  << distance_matrix[i][j].h_bonds[x].h_bond_length 
								 				  << endl;
									
									edgeAtribHbondDA << distance_matrix[i][j].h_bonds[x].don_code
											 		 << "_" 
											 		 << distance_matrix[i][j].h_bonds[x].don_num
											 		 << " (rr) "
											 		 << distance_matrix[i][j].h_bonds[x].acc_code
													 << "_"
													 << distance_matrix[i][j].h_bonds[x].acc_num
													 << "\t=\t"
													 << distance_matrix[i][j].h_bonds[x].atom_don_code
													 << "->"
													 << distance_matrix[i][j].h_bonds[x].atom_acc_code
											 		 << endl;
									
									edgeAtribHbDAdistance << distance_matrix[i][j].h_bonds[x].don_code
											 	  		  << "_" 
											 			  << distance_matrix[i][j].h_bonds[x].don_num
											 			  << " (rr) "
											 			  << distance_matrix[i][j].h_bonds[x].acc_code
											 			  << "_"
														  << distance_matrix[i][j].h_bonds[x].acc_num
											  	  		  << "\t=\t"
														  << distance_matrix[i][j].h_bonds[x].h_bond_length
														  << endl;
									
									edgeAtribHbDHAangle << distance_matrix[i][j].h_bonds[x].don_code
											 			<< "_" 
											 			<< distance_matrix[i][j].h_bonds[x].don_num
											 			<< " (rr) "
											 			<< distance_matrix[i][j].h_bonds[x].acc_code
											 			<< "_"
														<< distance_matrix[i][j].h_bonds[x].acc_num
											 		 	<< "\t=\t"
														<< distance_matrix[i][j].h_bonds[x].h_bond_angle 
														<< endl;
								}
								else
								{
									sifFile << distance_matrix[i][j].h_bonds[x].don_code
											<< "_" 
											<< distance_matrix[i][j].h_bonds[x].don_num
											<< "\trr\t"
											<< distance_matrix[i][j].h_bonds[x].acc_code
											<< "_"
											<< distance_matrix[i][j].h_bonds[x].acc_num
											<< endl;
									
									edgeAtribAtom << distance_matrix[i][j].h_bonds[x].don_code 
								  				  << "_"
								  				  << distance_matrix[i][j].h_bonds[x].don_num 
								  				  << " (rr) " 
												  << distance_matrix[i][j].h_bonds[x].acc_code 
								  				  << "_" 
								  				  << distance_matrix[i][j].h_bonds[x].acc_num
								  				  << "\t=\t" 
												  << distance_matrix[i][j].atom_i_code
								  				  << "_" 
								  				  << distance_matrix[i][j].atom_j_code
								  				  << endl;
									
									edgeAtribDist << distance_matrix[i][j].h_bonds[x].don_code
								  				  << "_" 
								  				  << distance_matrix[i][j].h_bonds[x].don_num
								                  << " (rr) " 
								 				  << distance_matrix[i][j].h_bonds[x].acc_code 
								  				  << "_" 
								  				  << distance_matrix[i][j].h_bonds[x].acc_num 
								 				  << "\t=\t" 
								  				  << distance_matrix[i][j].distance
								 				  << endl;
									
									edgeAtribHbondDA << distance_matrix[i][j].h_bonds[x].don_code
											 		 << "_" 
											 		 << distance_matrix[i][j].h_bonds[x].don_num
											 		 << " (rr) "
											 		 << distance_matrix[i][j].h_bonds[x].acc_code
													 << "_"
													 << distance_matrix[i][j].h_bonds[x].acc_num
													 << "\t=\t"
													 << distance_matrix[i][j].h_bonds[x].atom_don_code
													 << "->"
													 << distance_matrix[i][j].h_bonds[x].atom_acc_code
											 		 << endl;
									
									edgeAtribHbDAdistance << distance_matrix[i][j].h_bonds[x].don_code
											 	  		  << "_" 
											 			  << distance_matrix[i][j].h_bonds[x].don_num
											 			  << " (rr) "
											 			  << distance_matrix[i][j].h_bonds[x].acc_code
											 			  << "_"
														  << distance_matrix[i][j].h_bonds[x].acc_num
											  	  		  << "\t=\t"
														  << distance_matrix[i][j].h_bonds[x].h_bond_length
														  << endl;
									
									edgeAtribHbDHAangle << distance_matrix[i][j].h_bonds[x].don_code
											 			<< "_" 
											 			<< distance_matrix[i][j].h_bonds[x].don_num
											 			<< " (rr) "
											 			<< distance_matrix[i][j].h_bonds[x].acc_code
											 			<< "_"
														<< distance_matrix[i][j].h_bonds[x].acc_num
											 		 	<< "\t=\t"
														<< distance_matrix[i][j].h_bonds[x].h_bond_angle 
														<< endl;
								}
							}
					}
					else
					{
					if (distance_matrix[i][j].is_disulfide_bond==true)
						{
							for (int x=0; x < distance_matrix[i][j].disulfide_bond.size(); x++)
							{
								sifFile << distance_matrix[i][j].aa_i_code
										<< "_" 
										<< i+1
										<< "\trr\t"
										<< distance_matrix[i][j].aa_j_code
										<< "_"
										<< j+1
										<< endl;
								
								edgeAtribAtom << distance_matrix[i][j].aa_i_code 
												<< "_"
												<< i+1
												<< " (rr) " 
												<< distance_matrix[i][j].aa_j_code
												<< "_" 
												<< j+1 
												<< "\t=\t" 
												<< distance_matrix[i][j].atom_i_code 
												<< "_" 
												<< distance_matrix[i][j].atom_j_code
												<< endl;
								
								edgeAtribDist << distance_matrix[i][j].aa_i_code 
											<< "_" 
											<< i+1 
											<< " (rr) " 
											<< distance_matrix[i][j].aa_j_code 
											<< "_" 
											<< j+1 
											<< "\t=\t" 
											<< distance_matrix[i][j].distance
											<< endl;
								
								edgeAtribDisulfideDistance << distance_matrix[i][j].aa_i_code
															<< "_"
															<< i+1
															<< " (rr) "
															<< distance_matrix[i][j].aa_j_code
															<< "_"
															<< j+1
															<< "\t=\t"
															<< distance_matrix[i][j].disulfide_bond[x].bond_length
															<< endl;
								
								edgeAtribDisulfideAngle << distance_matrix[i][j].aa_i_code
															<< "_"
															<< i+1
															<< " (rr) "
															<< distance_matrix[i][j].aa_j_code
															<< "_"
															<< j+1
															<< "\t=\t"
															<< distance_matrix[i][j].disulfide_bond[x].xss_angle
															<< endl;
							}
						}
					else
						{
							sifFile << distance_matrix[i][j].aa_i_code 
								<< "_"
								<< i+1 
								<< "\trr\t" 
								<< distance_matrix[i][j].aa_j_code 
								<< "_" 
								<< j+1 
								<< endl;
							
							edgeAtribAtom << distance_matrix[i][j].aa_i_code 
								<< "_"
								<< i+1
								<< " (rr) " 
								<< distance_matrix[i][j].aa_j_code
								<< "_" 
								<< j+1 
								<< "\t=\t" 
								<< distance_matrix[i][j].atom_i_code 
								<< "_" 
								<< distance_matrix[i][j].atom_j_code
								<< endl;
							
							edgeAtribDist << distance_matrix[i][j].aa_i_code 
											<< "_" 
											<< i+1 
											<< " (rr) " 
											<< distance_matrix[i][j].aa_j_code 
											<< "_" 
											<< j+1 
											<< "\t=\t" 
											<< distance_matrix[i][j].distance
											<< endl;
						}
					}
				}	
			}
		}
		
		//Chiusura dell'oggetto file	
		sifFile.close();
//------------------------------------------------------------------------------
		edgeAtribAtom.close();
//------------------------------------------------------------------------------
		edgeAtribDist.close();
//------------------------------------------------------------------------------
		edgeAtribHbondDA.close();
//------------------------------------------------------------------------------
		edgeAtribHbDAdistance.close();
//------------------------------------------------------------------------------
		edgeAtribHbDHAangle.close();
//------------------------------------------------------------------------------
		edgeAtribSaltDistance.close();
//------------------------------------------------------------------------------
		edgeAtribSaltAngle.close();
//------------------------------------------------------------------------------
		edgeAtribSaltPN.close();
//------------------------------------------------------------------------------
		edgeAtribDisulfideDistance.close();
//------------------------------------------------------------------------------
		edgeAtribDisulfideAngle.close();
//------------------------------------------------------------------------------
		cout << "Done!" << endl;
}

/*
	Stampa i file di rete e di attributi definiti da PrintFiles in modo differente a seconda
 	del metodo di calcolo lanciato precedentemente.
 
 	Viene creata una cartella all'interno del percorso del file .pdb di origine, con lo
 	stesso nome del file .pdb e all'interno vengono scritti i file creati da PrintFiles
*/

void StructureNetwork::PrintCytoscapeFiles(bool print_all_HB)
{	
	input_file_dir = input_file_path.substr(0, input_file_path.size()-4) + "/";
	
	//Crea la directory secondo il percorso stabilito e setta i privilegi di accesso massimi
	mkdir(input_file_dir.c_str(),0777); 
			
	if ((alpha==true)&&(closatom==false))
	{
		if (print_all_HB == true)
		{
			AlphaPrintFilesAllHbonds("Alpha_allHB_Net.sif", 
									 "Alpha_allHB_Edge_Atrib_Atom_Type.eda", 
									 "Atoms_Determine_Closest_Distance (class=java.lang.String)", 
									 "Alpha_allHB_Edge_Atrib_Closest_Distance.eda", 
									 "Distance_Between_Alpha_Carbons(A°) (class=java.lang.Double)", 
									 "Alpha_allHB_Edge_Atrib_HBond_DA.eda", 
									 "H_Bond_Donnor-H_Bond_Acceptor (class=java.lang.String)", 
									 "Alpha_allHB_Edge_Atrib_HB_DA_distance.eda", 
									 "Donnor-Acceptor_Distance(A°) (class=java.lang.Double)", 
									 "Alpha_allHB_Edge_Atrib_HB_DHA_angle.eda", 
									 "Donnor-H-Acceptor_Angle(degrees) (class=java.lang.Double)",
									 "Alpha_allHB_Edge_Atrib_Salt_Positive_Negative.eda",
							  		 "Positive_Residue-Negative_Residue (class=java.lang.String)",
							  		 "Alpha_allHB_Edge_Atrib_Salt_Distance.eda",
							  		 "Salt_Bridge_Distance(A°) (class=java.lang.Double)",
							  		 "Alpha_allHB_Edge_Atrib_Salt_Angle.eda",
							 		 "Salt_Bridge_Angle(degrees°) (class=java.lang.Double)",
									 "Alpha_allHB_Edge_Atrib_Disulfide_Distance.eda",
									 "Disulfide_Bond_Distance(A°) (class=java.lang.Double)",
									 "Alpha_allHB_Edge_Atrib_Disulfide_Angle.eda",
									 "Disulfide_Bond_Angle(degrees°) (class=java.lang.Double)");
			
			PrintReport("Alpha_allHB_Report_Table");
		}
		else
		{
			AlphaPrintFiles("Alpha_Net.sif", 
							"Alpha_Edge_Atrib_Atom_Type.eda", 
							"Atoms_Determine_Closest_Distance (class=java.lang.String)", 
							"Alpha_Edge_Atrib_Closest_Distance.eda", 
							"Distance_Between_Alpha_Carbons(A°) (class=java.lang.Double)",
							"Alpha_Edge_Atrib_H-bond.eda",
							"Is_H-bond (class=java.lang.String)",
							"Alpha_Edge_Atrib_Salt_Bridge.eda",
							"Is_Salt_Bridge (class=java.lang.String)",
							"Alpha_Edge_Atrib_Didulfide_Bond.eda",
							"Is_Disulfide_Bond (class=java.lang.String)");
			
			PrintReport("Alpha_Report_Table");
		}
	}	

	if ((closatom==true)&&(alpha==false))
	{
		if (print_all_HB == true)
		{
			ClosestPrintFilesAllHbonds("Closest_allHB_Net.sif", 
									   "Closest_allHB_Edge_Atrib_Atom_Type.eda", 
									   "Atoms_Determine_Closest_Distance (class=java.lang.String)",
									   "Closest_allHB_Edge_Atrib_Closest_Distance.eda", 
									   "Closest_Distance_Between_Atoms(A°) (class=java.lang.Double)", 
									   "Closest_allHB_Edge_Atrib_HBond_DA.eda", 
									   "H_bond_Donnor-H_Bond_Acceptor (class=java.lang.String)", 
									   "Closest_allHB_Edge_Atrib_HB_DA_distance.eda", 
									   "Donnor-Acceptor_Distance(A°) (class=java.lang.Double)", 
									   "Closest_allHB_Edge_Atrib_HB_DHA_angle.eda",
									   "Donnor-H-Acceptor_Angle(degrees) (class=java.lang.Double)",
									   "Closest_allHB_Edge_Atrib_Salt_Positive_Negative.eda",
							  		   "Positive_Residue-Negative_Residue (class=java.lang.String)",
							  		   "Closest_allHB_Edge_Atrib_Salt_Distance.eda",
							  		   "Salt_Bridge_Distance(A°) (class=java.lang.Double)",
							  		   "Closest_allHB_Edge_Atrib_Salt_Angle.eda",
							 		   "Salt_Bridge_Angle(degrees°) (class=java.lang.Double)",
									   "Closest_allHB_Edge_Atrib_Disulfide_Distance.eda",
									   "Disulfide_Bond_Distance(A°) (class=java.lang.Double)",
									   "Closest_allHB_Edge_Atrib_Disulfide_Angle.eda",
									   "Disulfide_Bond_Angle(degrees°) (class=java.lang.Double)");
			
			PrintReport("Closest_allHB_Report_Table");
		}
		else
		{
			ClosestPrintFiles("Closest_Net.sif", 
							  "Closest_Edge_Atrib_Atom_Type.eda", 
							  "Atoms_Determine_Closest_Distance (class=java.lang.String)",
							  "Closest_Edge_Atrib_Closest_Distance.eda", 
							  "Closest_Distance_Between_Atoms(A°) (class=java.lang.Double)", 
							  "Closest_Edge_Atrib_HBond_DA.eda", 
							  "H_Bond_Donnor-H_Bond_Acceptor (class=java.lang.String)", 
							  "Closest_Edge_Atrib_HB_DA_Distance.eda", 
							  "Donnor-Acceptor_Distance(A°) (class=java.lang.Double)", 
							  "Closest_Edge_Atrib_HB_DHA_Angle.eda", 
							  "Donnor-H-Acceptor_Angle(degrees) (class=java.lang.Double)",
							  "Closest_Edge_Atrib_Salt_Positive_Negative.eda",
							  "Positive_Residue-Negative_Residue (class=java.lang.String)",
							  "Closest_Edge_Atrib_Salt_Distance.eda",
							  "Salt_Bridge_Distance(A°) (class=java.lang.Double)",
							  "Closest_Edge_Atrib_Salt_Angle.eda",
							  "Salt_Bridge_Angle(degrees°) (class=java.lang.Double)",
							  "Closest_Edge_Atrib_Disulfide_Distance.eda",
							  "Disulfide_Bond_Distance(A°) (class=java.lang.Double)",
							  "Closest_Edge_Atrib_Disulfide_Angle.eda",
							  "Disulfide_Bond_Angle(degrees°) (class=java.lang.Double)");
			
			PrintReport("Closest_Report_Table");
		}	
	}	
}

/*
 	Definisce i parametri della struttura di Hbons di default per ogni elemento della 	
	matrice di distanze. Richiamare questo metodo permette di rilanciare l'asegnazione dei 
	legami ad idrogeno
*/
void StructureNetwork::EraseHbons()
{
	for (int i = 0; i< distance_matrix.size(); i++)
	{
		for (int j = 0; j < distance_matrix[i].size(); j++)
			{
				distance_matrix[i][j].h_bonds.erase(distance_matrix[i][j].h_bonds.begin(), 				  distance_matrix[i][j].h_bonds.end());
			}
	}
}
								  
				
int StructureNetwork::ImportHydrogenBond(string input_file)
{
	
	int num_amino_donor, num_amino_acceptor, err;
	string atom_type_donor, atom_type_acceptor;
	double acceptor_donnor_distance, h_bond_angle;
	
/* 
int system ( const char * command );

Lancia una riga di comando da shell.

Execute system command

Invokes the command processor to execute a command. Once the command execution has terminated, the processor gives the control back to the program, returning an int value, whose interpretation is system-dependent.

The function call also be used with NULL as argument to check whether a command processor exists.

Parameters

command
    C string containing the system command to be executed.

Return Value
The value returned when the argument passed is not NULL, depends on the running environment specifications. In many systems, 0 is used to indicate that the command was succesfully executed and other values to indicate some sort of error.
When the argument passed is NULL, the function returns a nonzero value if the command processor is available, and zero otherwise.
*/
	
	string command = "./pass_H_bond.pl " + input_file;
	
/*
	HBPLUS v 3.0
	Hydrogen Bond Calculation Program
	http://www.biochem.ucl.ac.uk/bsm/hbplus/home.html
*/

	err = system (command.c_str());
	
	if (err != 0) 
	{
		cout << "error in execution of the script for the calculation of hydrogen bonds" 
			 << endl; 
		return 1;
	}
	
	string input_pass_h_bond = "./OUTPUT_pass_H_bond";
	
	EraseHbons();
	
	ifstream input(input_pass_h_bond.c_str());
	
	while (input.peek() != '0' && !input.eof())//termina lettura file esattamente alla fine
		{
			input >> num_amino_donor 
				  >> atom_type_donor 
				  >> num_amino_acceptor
		  		  >> atom_type_acceptor 
				  >> acceptor_donnor_distance 
				  >> h_bond_angle;
			
			HBonds tmp;
			bool stop = false;
			
			for (int i = 0; i< distance_matrix.size(); i++)
			{
				for (int j = 0; j < distance_matrix[i].size(); j++)
				{	
					
	  				if ((distance_matrix[i][j].distance != 0.0)&&((i+1==num_amino_donor)
						&&(j+1==num_amino_acceptor))||((j+1==num_amino_donor)
						&&(i+1==num_amino_acceptor)))
						
					{
						distance_matrix[i][j].is_h_bond = true;
						tmp.don_num = 		num_amino_donor;
						tmp.acc_num = 		num_amino_acceptor;
						tmp.atom_don_code = atom_type_donor;
						tmp.atom_acc_code = atom_type_acceptor;
						tmp.h_bond_length = acceptor_donnor_distance;
						tmp.h_bond_angle =	h_bond_angle;
						tmp.don_code =		sp.getAmino(num_amino_donor-1).getType1L();
						tmp.acc_code =		sp.getAmino(num_amino_acceptor-1).getType1L();
						
/*Controllo se ho altri legami ad H segnati come principali; se ne trovo altri la variabile stop diventa vera
e la condizione successiva di assegnazione di legame ad H principale non viene soddisfatta. In pratica dopo il
primo legame ad H identificato come principale non ne vengono più indicati altri*/
						
						
						for (int x=0; x < distance_matrix[i][j].h_bonds.size(); x++)							
							{
								if (distance_matrix[i][j].h_bonds[x].is_main == true)
									stop = true;
							}
						
/*Controllo se il legame ad H importato è definito tra gli stessi atomi che determinano la distanza minima che definisce il contatto
se tale legame ha le caratteristiche richieste (stessa distanza, stessi atomi coinvolti e non è ancora stato definito un altro
legame principale), viene definito come principale*/	
						
						if ((distance_matrix[i][j].distance - acceptor_donnor_distance <= 0.01)&&
							(acceptor_donnor_distance - distance_matrix[i][j].distance <= 0.01)&&
							((distance_matrix[i][j].atom_i_code==atom_type_donor)&&(distance_matrix[i][j].atom_j_code==atom_type_acceptor)||
							 (distance_matrix[i][j].atom_j_code==atom_type_donor)&&(distance_matrix[i][j].atom_i_code==atom_type_acceptor))&&(stop==false))
						{	
							   tmp.is_main = true;
							   //distance_matrix[i][j].is_h_bond = true;
						}
						
						distance_matrix[i][j].h_bonds.push_back(tmp);
						
					}
				
				}
			}
			skipToNewLine(input);
		}
	input.close();
	
	err = system ("rm -f OUTPUT_pass_H_bond");
	
//------------------------------------------------------------------------------
/*/SCRITTURA TABELLA
	
	string hydrogen_bond_table_path = "idrogen_bond_table";
	string ciccio = input_file_path.substr(0, input_file_path.size()-4) + "/";
	string input_file_path_pass = ciccio + hydrogen_bond_table_path;
	ofstream hydrogenFile(input_file_path_pass.c_str());
	
	hydrogenFile << input_file << "\n\n"
				 << "i" << "\t"
				 << "j" << "\t"
				 << "i_code" << "\t"
				 << "j_code" << "\t"
				 << "atom_i" << "\t"
				 << "atom_j" << "\t"
				 << "distance" << "\t"
				 << "is h bond" << "\t"
				 << "Hbond" << "\n"
				 << endl;
	
	for (int i = 0; i< distance_matrix.size(); i++)
			{
				for (int j = 0; j < distance_matrix[i].size(); j++)
				{
					if (distance_matrix[i][j].distance != 0.0)
					{	
						hydrogenFile 
							 << i+1 << "\t"
							 << j+1 << "\t"
							 << distance_matrix[i][j].aa_i_code << "\t"
							 << distance_matrix[i][j].aa_j_code << "\t"
							 << distance_matrix[i][j].atom_i_code << "\t"
							 << distance_matrix[i][j].atom_j_code << "\t"
							 << MyRound(distance_matrix[i][j].distance, 2) << "\t\t"
							 << distance_matrix[i][j].is_h_bond << "\t\t"
							 << distance_matrix[i][j].h_bonds.size() << "\t\n"
							 << "-------------------------------------------------------"
							 << endl;
							
							for (int x=0; x < distance_matrix[i][j].h_bonds.size(); x++)
							{	
							 hydrogenFile
								<< "is main" << "\t"
				 				<< "don_num" << "\t"
								<< "acc_num" << "\t\t"
				 				<< "atom_don_code" << "\t"
				 				<< "atom_acc_code" << "\t"
				 				<< "h_bond_length" << "\t"
				 				<< "h_bond_angle" << "\n";
								
								if (distance_matrix[i][j].h_bonds[x].is_main)
							 		hydrogenFile << 1 << "\t";
								else
							 		hydrogenFile << 0 << "\t";

 							 	hydrogenFile << distance_matrix[i][j].h_bonds[x].don_num << "\t"
							 	<< distance_matrix[i][j].h_bonds[x].acc_num << "\t\t"
								<< distance_matrix[i][j].h_bonds[x].atom_don_code << "\t\t"
		 					 	<< distance_matrix[i][j].h_bonds[x].atom_acc_code << "\t\t"
							 	<< distance_matrix[i][j].h_bonds[x].h_bond_length << "\t\t"
								<< distance_matrix[i][j].h_bonds[x].h_bond_angle << "\t"
							 	<< endl;
							}
						
						hydrogenFile 
						<< "-------------------------------------------------------" 
						<< endl;
					}
				}
			}
	hydrogenFile.close();*/
}

/*
	Stampa gli elementi di una cella della matrice di distanze in 3 file acquisibili
 	da Cytoscape:
 
 	-sif_name: file .sif che definisce i contatti fra i nodi
 
 	-edge_atrib_name: file di attributo .EA che definisce come attributo di ciascun contatto
 	 quali sono gli atomi che determinano tale contatto
 	
 	-edge_distance: file di attributo .EA che definisce come attributo di ciascun contatto
 	 la distanza di tale contatto
 
 	La prima riga di ogni file di attributo deve contenere una intestazione che determina
 	il tipo di dato che definisce l'attributo:
 	-es: Edge_Atrib_Atom_Alpha (class=java.lang.XXXX)
	 	 con XXXX = String	(stringa di caratteri)
		 			Double	(numero decimale)
		 			Integer	(numero intero)
*/
void  StructureNetwork::AlphaPrintFilesAllHbonds(string net_sif_file, 
								   string edge_atrib_atom_type, 
								   string edge_atrib_atom_type_header, 
								   string edge_atrib_distance, 
								   string edge_atrib_distance_header, 
								   string edge_atrib_hbond_DA, 
								   string edge_atrib_hbond_DA_header, 
								   string edge_atrib_hb_DA_distance, 
								   string edge_atrib_hb_DA_distance_header, 
								   string edge_atrib_hb_DHA_angle, 
								   string edge_atrib_hb_DHA_angle_header,
								   string edge_atrib_salt_P_N,
								   string edge_atrib_salt_P_N_header,
								   string edge_atrib_salt_distance,
								   string edge_atrib_salt_distance_header,
								   string edge_atrib_salt_angle,
								   string edge_atrib_salt_angle_header,
								   string edge_atrib_disulfide_distance,
								   string edge_atrib_disulfide_distance_header,
								   string edge_atrib_disulfide_angle,
								   string edge_atrib_disulfide_angle_header)
{
		string input_file_path_pass;
//------------------------------------------------------------------------------			
		input_file_path_pass = input_file_dir + net_sif_file;
	
		ofstream sifFile(input_file_path_pass.c_str()); 
//------------------------------------------------------------------------------
		input_file_path_pass = input_file_dir + edge_atrib_atom_type;

		ofstream edgeAtribAtom(input_file_path_pass.c_str());

		edgeAtribAtom << edge_atrib_atom_type_header << endl;
//------------------------------------------------------------------------------
		input_file_path_pass = input_file_dir + edge_atrib_distance;

		ofstream edgeAtribDist(input_file_path_pass.c_str());

		edgeAtribDist << edge_atrib_distance_header << endl;
//------------------------------------------------------------------------------
		input_file_path_pass = input_file_dir + edge_atrib_hbond_DA;
	
		ofstream edgeAtribHbondDA(input_file_path_pass.c_str());
	
		edgeAtribHbondDA << edge_atrib_hbond_DA_header << endl;
//------------------------------------------------------------------------------
		input_file_path_pass = input_file_dir + edge_atrib_hb_DA_distance;
		
		ofstream edgeAtribHbDAdistance(input_file_path_pass.c_str());
	
		edgeAtribHbDAdistance << edge_atrib_hb_DA_distance_header << endl;
//------------------------------------------------------------------------------
		input_file_path_pass = input_file_dir + edge_atrib_hb_DHA_angle;
	
	 	ofstream edgeAtribHbDHAangle(input_file_path_pass.c_str());
	
		edgeAtribHbDHAangle << edge_atrib_hb_DHA_angle_header << endl;
//------------------------------------------------------------------------------
		input_file_path_pass = input_file_dir + edge_atrib_salt_P_N;
	
		ofstream edgeAtribSaltPN(input_file_path_pass.c_str());
	
		edgeAtribSaltPN << edge_atrib_salt_P_N_header << endl;
//------------------------------------------------------------------------------
		input_file_path_pass = input_file_dir + edge_atrib_salt_distance;
		
		ofstream edgeAtribSaltDistance(input_file_path_pass.c_str());
	
		edgeAtribSaltDistance << edge_atrib_salt_distance_header << endl;
//------------------------------------------------------------------------------
		input_file_path_pass = input_file_dir + edge_atrib_salt_angle;
	
		ofstream edgeAtribSaltAngle(input_file_path_pass.c_str());
	
		edgeAtribSaltAngle << edge_atrib_salt_angle_header << endl;
//------------------------------------------------------------------------------
		input_file_path_pass = input_file_dir + edge_atrib_disulfide_distance;
	
		ofstream edgeAtribDisulfideDistance(input_file_path_pass.c_str());
	
		edgeAtribDisulfideDistance << edge_atrib_disulfide_distance_header << endl;
//------------------------------------------------------------------------------
		input_file_path_pass = input_file_dir + edge_atrib_disulfide_angle;
	
		ofstream edgeAtribDisulfideAngle(input_file_path_pass.c_str());
	
		edgeAtribDisulfideAngle << edge_atrib_disulfide_angle_header << endl;
//------------------------------------------------------------------------------		

		
		for (int i = 0; i< distance_matrix.size(); i++)
			
			for (int j = 0; j < distance_matrix[i].size(); j++)
			{
	  			if (distance_matrix[i][j].distance != 0.0)
				{	
					if (distance_matrix[i][j].is_salt_bridge==true)
					{
						
						for (int x=0; x < distance_matrix[i][j].salt_bridge.size(); x++)
						{	
							sifFile << distance_matrix[i][j].salt_bridge[x].positive_code
									<< "_" 
									<< distance_matrix[i][j].salt_bridge[x].positive_num
									<< "\trr\t"
									<< distance_matrix[i][j].salt_bridge[x].negative_code
									<< "_"
									<< distance_matrix[i][j].salt_bridge[x].negative_num
									<< endl;
							
					edgeAtribAtom << distance_matrix[i][j].salt_bridge[x].positive_code
								  << "_"
								  << distance_matrix[i][j].salt_bridge[x].positive_num
								  << " (rr) " 
								  << distance_matrix[i][j].salt_bridge[x].negative_code
								  << "_" 
								  << distance_matrix[i][j].salt_bridge[x].negative_num
								  << "\t=\t" 
								  << distance_matrix[i][j].salt_bridge[x].atom_positive_code 
								  << "_" 
								  << distance_matrix[i][j].salt_bridge[x].atom_negative_code
								  << endl;
							
					edgeAtribDist << distance_matrix[i][j].salt_bridge[x].positive_code
								  << "_" 
								  << distance_matrix[i][j].salt_bridge[x].positive_num
								  << " (rr) " 
								  << distance_matrix[i][j].salt_bridge[x].negative_code
								  << "_" 
								  << distance_matrix[i][j].salt_bridge[x].negative_num
								  << "\t=\t" 
								  << distance_matrix[i][j].distance
								  << endl;
							
				 edgeAtribSaltPN << distance_matrix[i][j].salt_bridge[x].positive_code
								 << "_" 
								 << distance_matrix[i][j].salt_bridge[x].positive_num
								 << " (rr) "
								 << distance_matrix[i][j].salt_bridge[x].negative_code
								 << "_"
								 << distance_matrix[i][j].salt_bridge[x].negative_num
								 << "\t=\t"
								 << distance_matrix[i][j].salt_bridge[x].positive_code
								 << "->"
								 << distance_matrix[i][j].salt_bridge[x].negative_code
								 << endl;
			
									
			edgeAtribSaltDistance << distance_matrix[i][j].salt_bridge[x].positive_code
								  << "_" 
								  << distance_matrix[i][j].salt_bridge[x].positive_num
								  << " (rr) "
								  << distance_matrix[i][j].salt_bridge[x].negative_code
								  << "_"
								  << distance_matrix[i][j].salt_bridge[x].negative_num
								  << "\t=\t"
								  << distance_matrix[i][j].salt_bridge[x].bridge_length
								  << endl;
									
			   edgeAtribSaltAngle << distance_matrix[i][j].salt_bridge[x].positive_code
								  << "_" 
								  << distance_matrix[i][j].salt_bridge[x].positive_num
								  << " (rr) "
								  << distance_matrix[i][j].salt_bridge[x].negative_code
								  << "_"
								  << distance_matrix[i][j].salt_bridge[x].negative_num
								  << "\t=\t"
								  << distance_matrix[i][j].salt_bridge[x].bridge_angle 
								  << endl;
							
						}
					}
						else
						{
							if(distance_matrix[i][j].h_bonds.size()!=0)
							{
								for (int x=0; x < distance_matrix[i][j].h_bonds.size(); x++)
								{
									sifFile << distance_matrix[i][j].h_bonds[x].don_code
											<< "_" 
											<< distance_matrix[i][j].h_bonds[x].don_num
											<< "\trr\t"
											<< distance_matrix[i][j].h_bonds[x].acc_code
											<< "_"
											<< distance_matrix[i][j].h_bonds[x].acc_num
											<< endl;
								
									edgeAtribAtom << distance_matrix[i][j].h_bonds[x].don_code 
								  				  << "_"
								  				  << distance_matrix[i][j].h_bonds[x].don_num 
								  				  << " (rr) " 
												  << distance_matrix[i][j].h_bonds[x].acc_code 
								  				  << "_" 
								  				  << distance_matrix[i][j].h_bonds[x].acc_num
								  				  << "\t=\t" 
												  << distance_matrix[i][j].atom_i_code
								  				  << "_" 
								  				  << distance_matrix[i][j].atom_j_code
								  				  << endl;
								
									edgeAtribDist << distance_matrix[i][j].h_bonds[x].don_code
								  				  << "_" 
								  				  << distance_matrix[i][j].h_bonds[x].don_num
								                  << " (rr) " 
								 				  << distance_matrix[i][j].h_bonds[x].acc_code 
								  				  << "_" 
								  				  << distance_matrix[i][j].h_bonds[x].acc_num 
								 				  << "\t=\t" 
								  				  << distance_matrix[i][j].distance 
								 				  << endl;
									
									
									edgeAtribHbondDA << distance_matrix[i][j].h_bonds[x].don_code
											 		 << "_" 
											 		 << distance_matrix[i][j].h_bonds[x].don_num
											 		 << " (rr) "
											 		 << distance_matrix[i][j].h_bonds[x].acc_code
													 << "_"
													 << distance_matrix[i][j].h_bonds[x].acc_num
													 << "\t=\t"
													 << distance_matrix[i][j].h_bonds[x].atom_don_code
													 << "->"
													 << distance_matrix[i][j].h_bonds[x].atom_acc_code
											 		 << endl;
									
									edgeAtribHbDAdistance << distance_matrix[i][j].h_bonds[x].don_code
											 	  		  << "_" 
											 			  << distance_matrix[i][j].h_bonds[x].don_num
											 			  << " (rr) "
											 			  << distance_matrix[i][j].h_bonds[x].acc_code
											 			  << "_"
														  << distance_matrix[i][j].h_bonds[x].acc_num
											  	  		  << "\t=\t"
														  << distance_matrix[i][j].h_bonds[x].h_bond_length
														  << endl;
									
									edgeAtribHbDHAangle << distance_matrix[i][j].h_bonds[x].don_code
											 			<< "_" 
											 			<< distance_matrix[i][j].h_bonds[x].don_num
											 			<< " (rr) "
											 			<< distance_matrix[i][j].h_bonds[x].acc_code
											 			<< "_"
														<< distance_matrix[i][j].h_bonds[x].acc_num
											 		 	<< "\t=\t"
														<< distance_matrix[i][j].h_bonds[x].h_bond_angle 
														<< endl;
								}
							}
							else
							{	
								if (distance_matrix[i][j].is_disulfide_bond==true)
								{
									for (int x=0; x < distance_matrix[i][j].disulfide_bond.size(); x++)
										{
											sifFile << distance_matrix[i][j].aa_i_code
												<< "_" 
												<< i+1
												<< "\trr\t"
												<< distance_matrix[i][j].aa_j_code
												<< "_"
												<< j+1
												<< endl;
								
										edgeAtribAtom << distance_matrix[i][j].aa_i_code 
														<< "_"
														<< i+1
														<< " (rr) " 
														<< distance_matrix[i][j].aa_j_code
														<< "_" 
														<< j+1 
														<< "\t=\t" 
														<< distance_matrix[i][j].atom_i_code 
														<< "_" 
														<< distance_matrix[i][j].atom_j_code
														<< endl;
								
											edgeAtribDist << distance_matrix[i][j].aa_i_code 
														  << "_" 
														  << i+1 
														  << " (rr) " 
														  << distance_matrix[i][j].aa_j_code 
													  	  << "_" 
														  << j+1 
														  << "\t=\t" 
														  << distance_matrix[i][j].distance
														  << endl;
								
								edgeAtribDisulfideDistance << distance_matrix[i][j].aa_i_code
															<< "_"
															<< i+1
															<< " (rr) "
															<< distance_matrix[i][j].aa_j_code
															<< "_"
															<< j+1
															<< "\t=\t"
															<< distance_matrix[i][j].disulfide_bond[x].bond_length
															<< endl;
								
								edgeAtribDisulfideAngle << distance_matrix[i][j].aa_i_code
															<< "_"
															<< i+1
															<< " (rr) "
															<< distance_matrix[i][j].aa_j_code
															<< "_"
															<< j+1
															<< "\t=\t"
															<< distance_matrix[i][j].disulfide_bond[x].xss_angle
															<< endl;
										}	
								}
								else
								{
							sifFile << distance_matrix[i][j].aa_i_code 
									<< "_"
									<< i+1 
									<< "\trr\t" 
									<< distance_matrix[i][j].aa_j_code 
									<< "_" 
									<< j+1 
									<< endl;
						
						edgeAtribAtom << distance_matrix[i][j].aa_i_code 
								  	<< "_"
								  	<< i+1
								  	<< " (rr) " 
								  	<< distance_matrix[i][j].aa_j_code
								  	<< "_" 
								  	<< j+1 
								  	<< "\t=\t" 
								  	<< distance_matrix[i][j].atom_i_code 
								  	<< "_" 
								  	<< distance_matrix[i][j].atom_j_code
								  	<< endl;
						
					edgeAtribDist << distance_matrix[i][j].aa_i_code 
								  << "_" 
								  << i+1 
								  << " (rr) " 
								  << distance_matrix[i][j].aa_j_code 
								  << "_" 
								  << j+1 
								  << "\t=\t" 
								  << distance_matrix[i][j].distance
								  << endl;					
								}
							}
						}
					}
					
				}
			
		
		//Chiusura dell'oggetto file	
		sifFile.close();
//------------------------------------------------------------------------------
		edgeAtribAtom.close();
//------------------------------------------------------------------------------
		edgeAtribDist.close();
//------------------------------------------------------------------------------
		edgeAtribHbondDA.close();
//------------------------------------------------------------------------------
		edgeAtribHbDAdistance.close();
//------------------------------------------------------------------------------
		edgeAtribHbDHAangle.close();
//------------------------------------------------------------------------------
		edgeAtribSaltDistance.close();
//------------------------------------------------------------------------------
		edgeAtribSaltAngle.close();
//------------------------------------------------------------------------------
		edgeAtribSaltPN.close();
//------------------------------------------------------------------------------
		edgeAtribDisulfideDistance.close();
//------------------------------------------------------------------------------
		edgeAtribDisulfideAngle.close();
//------------------------------------------------------------------------------
		cout << "Done!" << endl;
}


void  StructureNetwork::ClosestPrintFiles(string net_sif_file, 
								   string edge_atrib_atom_type, 
								   string edge_atrib_atom_type_header, 
								   string edge_atrib_distance, 
								   string edge_atrib_distance_header, 
								   string edge_atrib_hbond_DA, 
								   string edge_atrib_hbond_DA_header, 
								   string edge_atrib_hb_DA_distance, 
								   string edge_atrib_hb_DA_distance_header, 
								   string edge_atrib_hb_DHA_angle, 
								   string edge_atrib_hb_DHA_angle_header,
								   string edge_atrib_salt_P_N,
								   string edge_atrib_salt_P_N_header,
								   string edge_atrib_salt_distance,
								   string edge_atrib_salt_distance_header,
								   string edge_atrib_salt_angle,
								   string edge_atrib_salt_angle_header,
								   string edge_atrib_disulfide_distance,
								   string edge_atrib_disulfide_distance_header,
								   string edge_atrib_disulfide_angle,
								   string edge_atrib_disulfide_angle_header)

{
		string input_file_path_pass;
//------------------------------------------------------------------------------			
		input_file_path_pass = input_file_dir + net_sif_file;
	
		ofstream sifFile(input_file_path_pass.c_str()); 
//------------------------------------------------------------------------------
		input_file_path_pass = input_file_dir + edge_atrib_atom_type;

		ofstream edgeAtribAtom(input_file_path_pass.c_str());

		edgeAtribAtom << edge_atrib_atom_type_header << endl;
//------------------------------------------------------------------------------
		input_file_path_pass = input_file_dir + edge_atrib_distance;

		ofstream edgeAtribDist(input_file_path_pass.c_str());

		edgeAtribDist << edge_atrib_distance_header << endl;
//------------------------------------------------------------------------------
		input_file_path_pass = input_file_dir + edge_atrib_hbond_DA;
	
		ofstream edgeAtribHbondDA(input_file_path_pass.c_str());
	
		edgeAtribHbondDA << edge_atrib_hbond_DA_header << endl;
//------------------------------------------------------------------------------
		input_file_path_pass = input_file_dir + edge_atrib_hb_DA_distance;
		
		ofstream edgeAtribHbDAdistance(input_file_path_pass.c_str());
	
		edgeAtribHbDAdistance << edge_atrib_hb_DA_distance_header << endl;
//------------------------------------------------------------------------------
		input_file_path_pass = input_file_dir + edge_atrib_hb_DHA_angle;
	
	 	ofstream edgeAtribHbDHAangle(input_file_path_pass.c_str());
	
		edgeAtribHbDHAangle << edge_atrib_hb_DHA_angle_header << endl;
//------------------------------------------------------------------------------
		input_file_path_pass = input_file_dir + edge_atrib_salt_P_N;
	
		ofstream edgeAtribSaltPN(input_file_path_pass.c_str());
	
		edgeAtribSaltPN << edge_atrib_salt_P_N_header << endl;
//------------------------------------------------------------------------------
		input_file_path_pass = input_file_dir + edge_atrib_salt_distance;
		
		ofstream edgeAtribSaltDistance(input_file_path_pass.c_str());
	
		edgeAtribSaltDistance << edge_atrib_salt_distance_header << endl;
//------------------------------------------------------------------------------
		input_file_path_pass = input_file_dir + edge_atrib_salt_angle;
	
		ofstream edgeAtribSaltAngle(input_file_path_pass.c_str());
	
		edgeAtribSaltAngle << edge_atrib_salt_angle_header << endl;
//------------------------------------------------------------------------------
		input_file_path_pass = input_file_dir + edge_atrib_disulfide_distance;
	
		ofstream edgeAtribDisulfideDistance(input_file_path_pass.c_str());
	
		edgeAtribDisulfideDistance << edge_atrib_disulfide_distance_header << endl;
//------------------------------------------------------------------------------
		input_file_path_pass = input_file_dir + edge_atrib_disulfide_angle;
	
		ofstream edgeAtribDisulfideAngle(input_file_path_pass.c_str());
	
		edgeAtribDisulfideAngle << edge_atrib_disulfide_angle_header << endl;
//------------------------------------------------------------------------------		
		
		for (int i = 0; i< distance_matrix.size(); i++)
			
			for (int j = 0; j < distance_matrix[i].size(); j++)
			{
	  			if (distance_matrix[i][j].distance != 0.0)
				{					
//--------------------------------------------------------------------------------------									
					if (distance_matrix[i][j].is_salt_bridge==true)
					{
						
						for (int x=0; x < distance_matrix[i][j].salt_bridge.size(); x++)
						{	
							sifFile << distance_matrix[i][j].salt_bridge[x].positive_code
									<< "_" 
									<< distance_matrix[i][j].salt_bridge[x].positive_num
									<< "\trr\t"
									<< distance_matrix[i][j].salt_bridge[x].negative_code
									<< "_"
									<< distance_matrix[i][j].salt_bridge[x].negative_num
									<< endl;
							
					edgeAtribAtom << distance_matrix[i][j].salt_bridge[x].positive_code
								  << "_"
								  << distance_matrix[i][j].salt_bridge[x].positive_num
								  << " (rr) " 
								  << distance_matrix[i][j].salt_bridge[x].negative_code
								  << "_" 
								  << distance_matrix[i][j].salt_bridge[x].negative_num
								  << "\t=\t" 
								  << distance_matrix[i][j].salt_bridge[x].atom_positive_code 
								  << "_" 
								  << distance_matrix[i][j].salt_bridge[x].atom_negative_code
								  << endl;
							
					edgeAtribDist << distance_matrix[i][j].salt_bridge[x].positive_code
								  << "_" 
								  << distance_matrix[i][j].salt_bridge[x].positive_num
								  << " (rr) " 
								  << distance_matrix[i][j].salt_bridge[x].negative_code
								  << "_" 
								  << distance_matrix[i][j].salt_bridge[x].negative_num
								  << "\t=\t" 
								  << distance_matrix[i][j].distance
								  << endl;
							
				 edgeAtribSaltPN << distance_matrix[i][j].salt_bridge[x].positive_code
								 << "_" 
								 << distance_matrix[i][j].salt_bridge[x].positive_num
								 << " (rr) "
								 << distance_matrix[i][j].salt_bridge[x].negative_code
								 << "_"
								 << distance_matrix[i][j].salt_bridge[x].negative_num
								 << "\t=\t"
								 << distance_matrix[i][j].salt_bridge[x].positive_code
								 << "->"
								 << distance_matrix[i][j].salt_bridge[x].negative_code
								 << endl;
			
									
			edgeAtribSaltDistance << distance_matrix[i][j].salt_bridge[x].positive_code
								  << "_" 
								  << distance_matrix[i][j].salt_bridge[x].positive_num
								  << " (rr) "
								  << distance_matrix[i][j].salt_bridge[x].negative_code
								  << "_"
								  << distance_matrix[i][j].salt_bridge[x].negative_num
								  << "\t=\t"
								  << distance_matrix[i][j].salt_bridge[x].bridge_length
								  << endl;
									
			   edgeAtribSaltAngle << distance_matrix[i][j].salt_bridge[x].positive_code
								  << "_" 
								  << distance_matrix[i][j].salt_bridge[x].positive_num
								  << " (rr) "
								  << distance_matrix[i][j].salt_bridge[x].negative_code
								  << "_"
								  << distance_matrix[i][j].salt_bridge[x].negative_num
								  << "\t=\t"
								  << distance_matrix[i][j].salt_bridge[x].bridge_angle 
								  << endl;
							
						}
					}	
					
					else
					{			
//--------------------------------------------------------------------------------------					
						if(distance_matrix[i][j].is_h_bond==true)
						{
							for (int x=0; x < distance_matrix[i][j].h_bonds.size(); x++)
							{
								
								if (distance_matrix[i][j].h_bonds[x].is_main==true)
								{
									sifFile << distance_matrix[i][j].h_bonds[x].don_code
											<< "_" 
											<< distance_matrix[i][j].h_bonds[x].don_num
											<< "\trr\t"
											<< distance_matrix[i][j].h_bonds[x].acc_code
											<< "_"
											<< distance_matrix[i][j].h_bonds[x].acc_num
											<< endl;
									
									edgeAtribAtom << distance_matrix[i][j].h_bonds[x].don_code 
								  				  << "_"
								  				  << distance_matrix[i][j].h_bonds[x].don_num 
								  				  << " (rr) " 
												  << distance_matrix[i][j].h_bonds[x].acc_code 
								  				  << "_" 
								  				  << distance_matrix[i][j].h_bonds[x].acc_num
								  				  << "\t=\t" 
												  << distance_matrix[i][j].h_bonds[x].atom_don_code
								  				  << "_" 
								  				  << distance_matrix[i][j].h_bonds[x].atom_acc_code
								  				  << endl;
									
									edgeAtribDist << distance_matrix[i][j].h_bonds[x].don_code
								  				  << "_" 
								  				  << distance_matrix[i][j].h_bonds[x].don_num
								                  << " (rr) " 
								 				  << distance_matrix[i][j].h_bonds[x].acc_code 
								  				  << "_" 
								  				  << distance_matrix[i][j].h_bonds[x].acc_num 
								 				  << "\t=\t" 
								  				  << distance_matrix[i][j].h_bonds[x].h_bond_length 
								 				  << endl;
									
									edgeAtribHbondDA << distance_matrix[i][j].h_bonds[x].don_code
											 		 << "_" 
											 		 << distance_matrix[i][j].h_bonds[x].don_num
											 		 << " (rr) "
											 		 << distance_matrix[i][j].h_bonds[x].acc_code
													 << "_"
													 << distance_matrix[i][j].h_bonds[x].acc_num
													 << "\t=\t"
													 << distance_matrix[i][j].h_bonds[x].atom_don_code
													 << "->"
													 << distance_matrix[i][j].h_bonds[x].atom_acc_code
											 		 << endl;
									
									edgeAtribHbDAdistance << distance_matrix[i][j].h_bonds[x].don_code
											 	  		  << "_" 
											 			  << distance_matrix[i][j].h_bonds[x].don_num
											 			  << " (rr) "
											 			  << distance_matrix[i][j].h_bonds[x].acc_code
											 			  << "_"
														  << distance_matrix[i][j].h_bonds[x].acc_num
											  	  		  << "\t=\t"
														  << distance_matrix[i][j].h_bonds[x].h_bond_length
														  << endl;
									
									edgeAtribHbDHAangle << distance_matrix[i][j].h_bonds[x].don_code
											 			<< "_" 
											 			<< distance_matrix[i][j].h_bonds[x].don_num
											 			<< " (rr) "
											 			<< distance_matrix[i][j].h_bonds[x].acc_code
											 			<< "_"
														<< distance_matrix[i][j].h_bonds[x].acc_num
											 		 	<< "\t=\t"
														<< distance_matrix[i][j].h_bonds[x].h_bond_angle 
														<< endl;
								}
								
							}
						}
						else
						{
							if (distance_matrix[i][j].is_disulfide_bond==true)
							{
								for (int x=0; x < distance_matrix[i][j].disulfide_bond.size(); x++)
								{
									sifFile << distance_matrix[i][j].aa_i_code
											<< "_" 
											<< i+1
											<< "\trr\t"
											<< distance_matrix[i][j].aa_j_code
											<< "_"
											<< j+1
											<< endl;
								
								edgeAtribAtom << distance_matrix[i][j].aa_i_code 
												<< "_"
												<< i+1
												<< " (rr) " 
												<< distance_matrix[i][j].aa_j_code
												<< "_" 
												<< j+1 
												<< "\t=\t" 
												<< distance_matrix[i][j].atom_i_code 
												<< "_" 
												<< distance_matrix[i][j].atom_j_code
												<< endl;
								
								edgeAtribDist << distance_matrix[i][j].aa_i_code 
											<< "_" 
											<< i+1 
											<< " (rr) " 
											<< distance_matrix[i][j].aa_j_code 
											<< "_" 
											<< j+1 
											<< "\t=\t" 
											<< distance_matrix[i][j].distance
											<< endl;
								
								edgeAtribDisulfideDistance << distance_matrix[i][j].aa_i_code
															<< "_"
															<< i+1
															<< " (rr) "
															<< distance_matrix[i][j].aa_j_code
															<< "_"
															<< j+1
															<< "\t=\t"
															<< distance_matrix[i][j].disulfide_bond[x].bond_length
															<< endl;
								
								edgeAtribDisulfideAngle << distance_matrix[i][j].aa_i_code
															<< "_"
															<< i+1
															<< " (rr) "
															<< distance_matrix[i][j].aa_j_code
															<< "_"
															<< j+1
															<< "\t=\t"
															<< distance_matrix[i][j].disulfide_bond[x].xss_angle
															<< endl;
								}
							}
							else
							{
								sifFile << distance_matrix[i][j].aa_i_code 
										<< "_"
										<< i+1 
										<< "\trr\t" 
										<< distance_matrix[i][j].aa_j_code 
										<< "_" 
										<< j+1 
										<< endl;
						
							edgeAtribAtom << distance_matrix[i][j].aa_i_code 
								 	  	 	<< "_"
								  			<< i+1
								  			<< " (rr) " 
								  			<< distance_matrix[i][j].aa_j_code
								 		 	<< "_" 
								  			<< j+1 
								 			<< "\t=\t" 
								 		 	<< distance_matrix[i][j].atom_i_code 
								  			<< "_" 
								  			<< distance_matrix[i][j].atom_j_code
								 	        << endl;
						
								edgeAtribDist << distance_matrix[i][j].aa_i_code 
								  				 << "_" 
								  				 << i+1 
								  				 << " (rr) " 
								 			 	 << distance_matrix[i][j].aa_j_code 
								 				 << "_" 
								 				 << j+1 
								 				 << "\t=\t" 
								 				 << distance_matrix[i][j].distance
								  			     << endl;					
							}
					
						}
					}	
				
				}
			}
		
		//Chiusura dell'oggetto file	
		sifFile.close();
//------------------------------------------------------------------------------
		edgeAtribAtom.close();
//------------------------------------------------------------------------------
		edgeAtribDist.close();
//------------------------------------------------------------------------------
		edgeAtribHbondDA.close();
//------------------------------------------------------------------------------
		edgeAtribHbDAdistance.close();
//------------------------------------------------------------------------------
		edgeAtribHbDHAangle.close();
//------------------------------------------------------------------------------
		edgeAtribSaltDistance.close();
//------------------------------------------------------------------------------
		edgeAtribSaltAngle.close();
//------------------------------------------------------------------------------
		edgeAtribSaltPN.close();
//------------------------------------------------------------------------------
		edgeAtribDisulfideDistance.close();
//------------------------------------------------------------------------------
		edgeAtribDisulfideAngle.close();
//------------------------------------------------------------------------------
		cout << "Done!" << endl;
}


void  StructureNetwork::AlphaPrintFiles(string net_sif_file, 
								   string edge_atrib_atom_type, 
								   string edge_atrib_atom_type_header, 
								   string edge_atrib_distance, 
								   string edge_atrib_distance_header,
								   string edge_atrib_hbond, 
								   string edge_atrib_hbond_header, 
								   string edge_atrib_salt,
								   string edge_atrib_salt_header,
								   string edge_atrib_disulfide,
								   string edge_atrib_disulfide_header)

{
		string input_file_path_pass;
//------------------------------------------------------------------------------			
		input_file_path_pass = input_file_dir + net_sif_file;
	
		ofstream sifFile(input_file_path_pass.c_str()); 
//------------------------------------------------------------------------------
		input_file_path_pass = input_file_dir + edge_atrib_atom_type;

		ofstream edgeAtribAtom(input_file_path_pass.c_str());

		edgeAtribAtom << edge_atrib_atom_type_header << endl;
//------------------------------------------------------------------------------
		input_file_path_pass = input_file_dir + edge_atrib_distance;

		ofstream edgeAtribDist(input_file_path_pass.c_str());

		edgeAtribDist << edge_atrib_distance_header << endl;
//------------------------------------------------------------------------------
		input_file_path_pass = input_file_dir + edge_atrib_hbond;
	
		ofstream edgeAtribHbond(input_file_path_pass.c_str());
	
		edgeAtribHbond << edge_atrib_hbond_header << endl;
//------------------------------------------------------------------------------
		input_file_path_pass = input_file_dir + edge_atrib_salt;
	
		ofstream edgeAtribSalt(input_file_path_pass.c_str());
	
		edgeAtribSalt << edge_atrib_salt_header << endl;
//------------------------------------------------------------------------------
		input_file_path_pass = input_file_dir + edge_atrib_disulfide;
	
		ofstream edgeAtribDisulfide(input_file_path_pass.c_str());
	
		edgeAtribDisulfide << edge_atrib_disulfide_header << endl;
//------------------------------------------------------------------------------
		
		for (int i = 0; i< distance_matrix.size(); i++)	
			for (int j = 0; j < distance_matrix[i].size(); j++)
			{
	  			if (distance_matrix[i][j].distance != 0.0)
					{
						if(distance_matrix[i][j].is_salt_bridge==true)
						{
							edgeAtribSalt << distance_matrix[i][j].aa_i_code
										  << "_"
										  << i+1
										  << " (rr) " 
										  << distance_matrix[i][j].aa_j_code
										  << "_"
										  << j+1
										  << "\t=\tyes"
										  << endl;
						}
						
						if(distance_matrix[i][j].is_h_bond==true && distance_matrix[i][j].is_salt_bridge==false)
						{
							edgeAtribHbond << distance_matrix[i][j].aa_i_code
										   << "_"
										   << i+1
										   << " (rr) " 
										   << distance_matrix[i][j].aa_j_code
										   << "_"
										   << j+1
										   << "\t=\tyes"
										   << endl;
						}
						
						if(distance_matrix[i][j].is_disulfide_bond==true)
						{
							edgeAtribDisulfide << distance_matrix[i][j].aa_i_code
										  	   << "_"
										       << i+1
										       << " (rr) " 
										       << distance_matrix[i][j].aa_j_code
										       << "_"
										       << j+1
										       << "\t=\tyes"
										       << endl;
						}
						
						sifFile << distance_matrix[i][j].aa_i_code 
								<< "_"
								<< i+1 
								<< "\trr\t" 
								<< distance_matrix[i][j].aa_j_code 
								<< "_" 
								<< j+1 
								<< endl;
							
						edgeAtribAtom << distance_matrix[i][j].aa_i_code 
									  << "_"
									  << i+1
									  << " (rr) " 
									  << distance_matrix[i][j].aa_j_code
									  << "_" 
									  << j+1 
									  << "\t=\t" 
									  << distance_matrix[i][j].atom_i_code 
									  << "_" 
									  << distance_matrix[i][j].atom_j_code
									  << endl;
							
						edgeAtribDist << distance_matrix[i][j].aa_i_code 
									  << "_" 
									  << i+1 
									  << " (rr) " 
									  << distance_matrix[i][j].aa_j_code 
									  << "_" 
									  << j+1 
									  << "\t=\t" 
									  << distance_matrix[i][j].distance
									  << endl;					
					}
			}	
		
		//Chiusura dell'oggetto file	
		sifFile.close();
//------------------------------------------------------------------------------
		edgeAtribAtom.close();
//------------------------------------------------------------------------------
		edgeAtribDist.close();
//------------------------------------------------------------------------------
		edgeAtribHbond.close();
//------------------------------------------------------------------------------
		edgeAtribDisulfide.close();
//------------------------------------------------------------------------------
		edgeAtribSalt.close();
//------------------------------------------------------------------------------
		cout << "Done!" << endl;
}


double StructureNetwork::MyRound (double num, int decimal)
{	
	int ten_power=1;
	
	for(int i=0; i<decimal; i++)
	{
		ten_power = ten_power*10;
	}
	
	return round(num*ten_power) / ten_power;
}

void StructureNetwork::EraseSaltBridge()
{
	for (int i = 0; i< distance_matrix.size(); i++)
	{
		for (int j = 0; j < distance_matrix[i].size(); j++)
			{
				distance_matrix[i][j].salt_bridge.erase(distance_matrix[i][j].salt_bridge.begin(), distance_matrix[i][j].salt_bridge.end());
			}
	}
}

void StructureNetwork::EraseDisulfideBond()
{
	for (int i = 0; i< distance_matrix.size(); i++)
	{
		for (int j = 0; j < distance_matrix[i].size(); j++)
			{
				distance_matrix[i][j].disulfide_bond.erase(distance_matrix[i][j].disulfide_bond.begin(), distance_matrix[i][j].disulfide_bond.end());
			}
	}
}

void StructureNetwork::CalculateSaltBridge()
{
	EraseSaltBridge();
	//ofstream salt_bridge_file("/home/michele/Modelli/Test_Salt_Bridge/salt_bridge_table");
	//salt_bridge_file << "Residuo i\tResiduo j\tpositivo\tnegativo\tDistanza\tAngolo\n" << endl;
	//salt_bridge_file << "Angolo" << endl;
	for (int i = 0; i< distance_matrix.size(); i++)
			{
				for (int j = 0; j < distance_matrix[i].size(); j++)
				{
					if((((distance_matrix[i][j].aa_i_code=='D')||(distance_matrix[i][j].aa_i_code=='E'))&&
					  	((distance_matrix[i][j].aa_j_code=='R')||(distance_matrix[i][j].aa_j_code=='K')||(distance_matrix[i][j].aa_j_code=='H')))||
						
					  (((distance_matrix[i][j].aa_i_code=='R')||(distance_matrix[i][j].aa_i_code=='K')||(distance_matrix[i][j].aa_i_code=='H'))&&
					  ((distance_matrix[i][j].aa_j_code=='D')||(distance_matrix[i][j].aa_j_code=='E'))))
					{
						vgVector3<double> mass_center_i, mass_center_j;
						double salt_bridge_distance, salt_bridge_angle;
					
						salt_bridge_distance = CalculateSaltDistance(i, j, distance_matrix[i][j].aa_i_code, distance_matrix[i][j].aa_j_code);
						
						salt_bridge_angle = CalculateSaltAngle(i, j, distance_matrix[i][j].aa_i_code, distance_matrix[i][j].aa_j_code);
						
						if (salt_bridge_distance <= 4.0)
						{
							distance_matrix[i][j].is_salt_bridge = true;			
							SaltBridge tmp;
							
							if ((distance_matrix[i][j].aa_i_code=='D')||(distance_matrix[i][j].aa_i_code=='E'))
							{
								tmp.negative_num = i+1;
								tmp.negative_code = distance_matrix[i][j].aa_i_code;
								tmp.atom_negative_code = distance_matrix[i][j].atom_i_code;
							}	
							
							
							if ((distance_matrix[i][j].aa_j_code=='D')||(distance_matrix[i][j].aa_j_code=='E'))
							{
								tmp.negative_num = j+1;
								tmp.negative_code = distance_matrix[i][j].aa_j_code;
								tmp.atom_negative_code = distance_matrix[i][j].atom_j_code;
							}
								
							if ((distance_matrix[i][j].aa_i_code=='R')||(distance_matrix[i][j].aa_i_code=='K')||(distance_matrix[i][j].aa_i_code=='H'))
							{
								tmp.positive_num = i+1;
								tmp.positive_code = distance_matrix[i][j].aa_i_code;
								tmp.atom_positive_code = distance_matrix[i][j].atom_i_code;
							}
								
							if ((distance_matrix[i][j].aa_j_code=='R')||(distance_matrix[i][j].aa_j_code=='K')||(distance_matrix[i][j].aa_j_code=='H'))
							{
								tmp.positive_num = j+1;
								tmp.positive_code = distance_matrix[i][j].aa_j_code;
								tmp.atom_positive_code = distance_matrix[i][j].atom_j_code;
							}
								
							tmp.bridge_length = salt_bridge_distance;
							tmp.bridge_angle = salt_bridge_angle;
							
							distance_matrix[i][j].salt_bridge.push_back(tmp);
						/*	
							salt_bridge_file << distance_matrix[i][j].aa_i_code << "_" << i+1 
							 			 	 << "\t\t" << distance_matrix[i][j].aa_j_code << "_" << j+1 
											 << "\t\t" << distance_matrix[i][j].salt_bridge[0].positive_num << "_" 
											 << distance_matrix[i][j].salt_bridge[0].positive_code 
											 << "\t\t"<< distance_matrix[i][j].salt_bridge[0].negative_num << "_"
											 << distance_matrix[i][j].salt_bridge[0].negative_code 
											 << "\t\t"<<  distance_matrix[i][j].salt_bridge[0].bridge_length 
								        	 <<"\t\t"<< distance_matrix[i][j].salt_bridge[0].bridge_angle << endl;
							//salt_bridge_file << salt_bridge_angle << endl;*/
						}
					
					}

				}
					
			}
	//salt_bridge_file.close();
}


vgVector3<double> StructureNetwork::CalculateMassCenter(int& i, char amino_code)
{
	vgVector3<double> mass_center;
	
						//Calcolo del centro di massa del gruppo carico dell'aa i
						switch (amino_code)
						{
							case 'K':
							{		
								mass_center = sp.getAmino(i).getSideChain()[NZ].getCoords();
								//cout << distance_matrix[i][j].aa_i_code << " le coordinate sono "<< i_coords << endl;
								break;
							}
								
							case 'R':
							{	
								mass_center = sp.getAmino(i).getSideChain()[CZ].getCoords();
								break;
							}
								
							case 'D':
							{
								vgVector3<double> i_coords_od1, i_coords_od2, i_coords_cg;
								i_coords_od1 = sp.getAmino(i).getSideChain()[OD1].getCoords();
								i_coords_od2 = sp.getAmino(i).getSideChain()[OD2].getCoords();
								i_coords_cg = sp.getAmino(i).getSideChain()[CG].getCoords();
								mass_center.x = MyRound(((i_coords_od1.x*16+i_coords_od2.x*16+i_coords_cg.x*12)/(16+16+12)),3);
								mass_center.y = MyRound(((i_coords_od1.y*16+i_coords_od2.y*16+i_coords_cg.y*12)/(16+16+12)),3);
								mass_center.z = MyRound(((i_coords_od1.z*16+i_coords_od2.z*16+i_coords_cg.z*12)/(16+16+12)),3);
								//cout << distance_matrix[i][j].aa_i_code << " le coordinate sono di nh1 "<< i_coords_od1 << "\tquelle di nh2 sono\t" << i_coords_od2 << "\nle coordinate medie sono\t"<< mass_center << endl;
								break;
							}
								
							case 'E':
							{
								vgVector3<double> i_coords_oe1, i_coords_oe2, i_coords_cd;
								i_coords_oe1 = sp.getAmino(i).getSideChain()[OE1].getCoords();
								i_coords_oe2 = sp.getAmino(i).getSideChain()[OE2].getCoords();
								i_coords_cd = sp.getAmino(i).getSideChain()[CD].getCoords();
								mass_center.x = MyRound(((i_coords_oe1.x*16+i_coords_oe2.x*16+i_coords_cd.x*12)/(16+16+12)),3);
								mass_center.y = MyRound(((i_coords_oe1.y*16+i_coords_oe2.y*16+i_coords_cd.y*12)/(16+16+12)),3);
								mass_center.z = MyRound(((i_coords_oe1.z*16+i_coords_oe2.z*16+i_coords_cd.z*12)/(16+16+12)),3);								
								//cout << distance_matrix[i][j].aa_i_code << " le coordinate sono di nh1 "<< i_coords_oe1 << "\tquelle di nh2 sono\t" << i_coords_oe2 << "\nle coordinate medie sono\t"<< mass_center << endl;
								break;
							}
								
								case 'H':
							{
								vgVector3<double> i_coords_nd1, i_coords_ne2, i_coords_ce1;
								i_coords_nd1 = sp.getAmino(i).getSideChain()[ND1].getCoords();
								i_coords_ne2 = sp.getAmino(i).getSideChain()[NE2].getCoords();
								i_coords_ce1 = sp.getAmino(i).getSideChain()[CE1].getCoords();
								mass_center.x = MyRound(((i_coords_nd1.x*15+i_coords_ne2.x*15+i_coords_ce1.x*12)/(15+15+12)),3);
								mass_center.y = MyRound(((i_coords_nd1.y*15+i_coords_ne2.y*15+i_coords_ce1.y*12)/(15+15+12)),3);
								mass_center.z = MyRound(((i_coords_nd1.z*15+i_coords_ne2.z*15+i_coords_ce1.z*12)/(15+15+12)),3);																
								break;
							}
						};
	return mass_center;
}

double StructureNetwork::CalculateSaltAngle(int& i, int& j, char aa_i_code, char aa_j_code)
{
	vgVector3<double> coord_c_alpha_i, coord_c_alpha_j, a_i, a_j, mass_center_i, mass_center_j;
	double salt_bridge_angle, cos_angle;
	
	mass_center_i = CalculateMassCenter(i, aa_i_code);
	mass_center_j = CalculateMassCenter(j, aa_j_code);
	
	coord_c_alpha_i = sp.getAmino(i)[CA].getCoords();
	coord_c_alpha_j = sp.getAmino(j)[CA].getCoords();
	
	a_i.x = coord_c_alpha_i.x-mass_center_i.x;
	a_i.y = coord_c_alpha_i.y-mass_center_i.y;
	a_i.z = coord_c_alpha_i.z-mass_center_i.z;
	
	a_j.x = coord_c_alpha_j.x-mass_center_j.x;
	a_j.y = coord_c_alpha_j.y-mass_center_j.y;
	a_j.z = coord_c_alpha_j.z-mass_center_j.z;
	
	cos_angle = ((a_i.x*a_j.x)+(a_i.y*a_j.y)+(a_i.z*a_j.z))/sqrt((pow(a_i.x,2)+pow(a_i.y,2)+pow(a_i.z,2))*(pow(a_j.x,2)+pow(a_j.y,2)+pow(a_j.z,2)));
	
	salt_bridge_angle = MyRound((acos(cos_angle)*180.0 / PI),2);
	return salt_bridge_angle;
}

double StructureNetwork::CalculateSaltDistance(int& i, int& j, char aa_i_code, char aa_j_code)
{
	vgVector3<double> mass_center_i,mass_center_j;
	double mass_centers_distance;
					
	mass_center_i = CalculateMassCenter(i, aa_i_code);
	mass_center_j = CalculateMassCenter(j, aa_j_code);
	mass_centers_distance = MyRound(sqrt(pow((mass_center_i.x-mass_center_j.x),2)+
													 pow((mass_center_i.y-mass_center_j.y),2)+
													 pow((mass_center_i.z-mass_center_j.z),2)),2);
	return mass_centers_distance;
}

void StructureNetwork::CalculateDisulfideBond()
{	
	EraseDisulfideBond();
	//string disulfide_bond_table_path = "disulfide_bond_table";
	//string ciccio = input_file_path.substr(0, input_file_path.size()-4) + "/";
	
	//string input_file_path_pass = ciccio + disulfide_bond_table_path;
	//ofstream disulfide_bond_file(input_file_path_pass.c_str());
	//disulfide_bond_file << "Residuo i\tResiduo j\tDistanza\tAngolo\n" << endl;

	for (int i = 0; i< distance_matrix.size(); i++)
			{
				for (int j = 0; j < distance_matrix[i].size(); j++)
				{
					if(distance_matrix[i][j].aa_i_code=='C' && distance_matrix[i][j].aa_j_code=='C' && (sp.getAmino(i).getSideChain()[SG].distance(sp.getAmino(j).getSideChain()[SG])<2.2))
					{	
						distance_matrix[i][j].is_disulfide_bond = true;
						
						DisulfideBond tmp;
					
						tmp.bond_length = MyRound((sp.getAmino(i).getSideChain()[SG].distance(sp.getAmino(j).getSideChain()[SG])),2);
						tmp.xss_angle = CalculateDisulfideXssAngle(i,j);
						
						distance_matrix[i][j].disulfide_bond.push_back(tmp);
						
						/*disulfide_bond_file << distance_matrix[i][j].aa_i_code << "_" << i+1 
							 			 	 << "\t\t" << distance_matrix[i][j].aa_j_code << "_" << j+1 
											 << "\t\t"<<  distance_matrix[i][j].disulfide_bond[0].bond_length 
								        	 <<"\t\t"<< distance_matrix[i][j].disulfide_bond[0].xss_angle << endl;*/
					}
				}
			}
	//disulfide_bond_file.close();
}

double StructureNetwork::CalculateDisulfideXssAngle(int& i, int& j)
{
	vgVector3<double> a_i, a_j,coords_CB_i,coords_SG_i,coords_CB_j,coords_SG_j;
	double cos_angle, disulfide_xss_angle;
	
	coords_CB_i = sp.getAmino(i).getSideChain()[CB].getCoords();
	coords_SG_i = sp.getAmino(i).getSideChain()[SG].getCoords();
	coords_CB_j = sp.getAmino(j).getSideChain()[CB].getCoords();
	coords_SG_j = sp.getAmino(j).getSideChain()[SG].getCoords();
	
	a_i.x = coords_CB_i.x-coords_SG_i.x;
	a_i.y = coords_CB_i.y-coords_SG_i.y;
	a_i.z = coords_CB_i.z-coords_SG_i.z;
	
	a_j.x = coords_CB_j.x-coords_SG_j.x;
	a_j.y = coords_CB_j.y-coords_SG_j.y;
	a_j.z = coords_CB_j.z-coords_SG_j.z;
	
	cos_angle = ((a_i.x*a_j.x)+(a_i.y*a_j.y)+(a_i.z*a_j.z))/sqrt((pow(a_i.x,2)+pow(a_i.y,2)+pow(a_i.z,2))*(pow(a_j.x,2)+pow(a_j.y,2)+pow(a_j.z,2)));
	
	disulfide_xss_angle = MyRound((acos(cos_angle)*180.0 / PI),2);
	
	return disulfide_xss_angle;
}

void StructureNetwork::PrintReport(string report_table_name)
{
	string report_table_path = input_file_path.substr(0, input_file_path.size()-4) + "/";
	string input_file_path_pass = report_table_path + report_table_name;
	ofstream reportTable(input_file_path_pass.c_str());
	
	string data = GetTime();
	
	reportTable  << "PDB TO CITOSCAPE REPORT\t\t\t\t" << data 
				 << "\n" << input_file_path <<"\n"<< endl;
	
	reportTable << "Residual i\t" << "Residual j\t" << "Atom i\t" << "Atom j\t" 
				<< "Distance\t" << "H-Bond Number\t" << "Salt Bridge\t" << "Disulfide Bond\n" << endl; 
	
	
	for (int i = 0; i< distance_matrix.size(); i++)
			{
				for (int j = 0; j < distance_matrix[i].size(); j++)
				{
					if (distance_matrix[i][j].distance != 0.0)
					{	
						string is_h_bond, is_salt_bridge, is_disulfide_bond;
						
						if (distance_matrix[i][j].is_h_bond == true)
							is_h_bond = "yes";
						else
							is_h_bond = "   ";
						
						if (distance_matrix[i][j].is_salt_bridge == true)
							is_salt_bridge = "yes";
						else
							is_salt_bridge = "   ";
						
						if (distance_matrix[i][j].is_disulfide_bond == true)
							is_disulfide_bond = "yes";
						else
							is_disulfide_bond = "   ";
						
						reportTable 
							 << distance_matrix[i][j].aa_i_code << "_"
							 << i+1 << "\t\t|"
							 << distance_matrix[i][j].aa_j_code << "_"
							 << j+1 << "\t\t|" 
							 << distance_matrix[i][j].atom_i_code << "\t|"
							 << distance_matrix[i][j].atom_j_code << "\t|"
							 << distance_matrix[i][j].distance << "\t\t|"
							 << distance_matrix[i][j].h_bonds.size() << "\t\t|"
							 << is_salt_bridge << "\t\t|"
							 << is_disulfide_bond << "\n"
							 << "--------------------------------------------------------------------------------------------------------------" << endl;
							 
							
							for (int x=0; x < distance_matrix[i][j].h_bonds.size(); x++)
							{
								reportTable << "\nH-BOND\n" << endl;
								
							 	reportTable	<< "main H-bond" << "\t"
				 							<< "donnor" << "\t"
											<< "acceptor" << "\t\t"
				 							<< "donnor atom" << "\t"
				 							<< "ecceptor atom" << "\t"
				 							<< "H-bond length" << "\t"
				 							<< "H-bond angle" << "\n";
								
								if (distance_matrix[i][j].h_bonds[x].is_main==true)
							 		reportTable << "yes" << "\t\t";
								else
							 		reportTable << "  " << "\t\t";

 							 	reportTable << distance_matrix[i][j].h_bonds[x].don_num << "_"
											<< distance_matrix[i][j].h_bonds[x].don_code << "\t"
							 				<< distance_matrix[i][j].h_bonds[x].acc_num << "_"
											<< distance_matrix[i][j].h_bonds[x].acc_code << "\t\t\t"
											<< distance_matrix[i][j].h_bonds[x].atom_don_code << "\t\t"
		 					 				<< distance_matrix[i][j].h_bonds[x].atom_acc_code << "\t\t"
							 				<< distance_matrix[i][j].h_bonds[x].h_bond_length << "\t\t"
											<< distance_matrix[i][j].h_bonds[x].h_bond_angle << "\t"
							 				<< endl;
							}
							
							for (int x=0; x < distance_matrix[i][j].salt_bridge.size(); x++)
							{
								reportTable << "\nSALT BRIDGE\n" << endl;
								
								reportTable	<< "Positive Residual" << "\t"
				 							<< "Negative Residual" << "\t"
											<< "Bridge Distance" << "\t\t"
				 							<< "Bridge Angle" << "\n";
								
								reportTable << distance_matrix[i][j].salt_bridge[x].positive_num << "_"
											<< distance_matrix[i][j].salt_bridge[x].positive_code << "\t\t\t"
							 				<< distance_matrix[i][j].salt_bridge[x].negative_num << "_"
											<< distance_matrix[i][j].salt_bridge[x].negative_code << "\t\t\t"
							 				<< distance_matrix[i][j].salt_bridge[x].bridge_length << "\t\t\t"
											<< distance_matrix[i][j].salt_bridge[x].bridge_angle
							 				<< endl;
							}
							
							for (int x=0; x < distance_matrix[i][j].disulfide_bond.size(); x++)
							{
								reportTable << "\nDISULFIDE BOND\n" << endl;
								
								reportTable	<< "Disulfide Bond Length" << "\t"
				 							<< "Disulfide Bond Xss Angle" << "\n";
								
								reportTable << distance_matrix[i][j].disulfide_bond[x].bond_length << "\t\t\t"
											<< distance_matrix[i][j].disulfide_bond[x].xss_angle
							 				<< endl;
							}
						
							reportTable
							<< "--------------------------------------------------------------------------------------------------------------" 
							<< endl;
						}
				}
			}
	reportTable.close();	
}


string StructureNetwork::GetTime()
{
  time_t rawtime;
  struct tm * timeinfo;

  time ( &rawtime );
  timeinfo = localtime ( &rawtime );
  return asctime (timeinfo);
}
